package bb.lanxing.device.sgdevcie.xpair

import android.graphics.drawable.AnimationDrawable
import android.view.View
import android.view.animation.AlphaAnimation
import androidx.core.content.res.ResourcesCompat
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import bb.lanxing.R
import bb.lanxing.databinding.FragmentXpairSearchBinding
import bb.lanxing.databinding.LayoutXpairIntroItemBinding
import bb.lanxing.device.sgdevcie.utils.SearchDeviceAdapter
import bb.lanxing.device.sgdevcie.xpair.uimodel.BleDescriptionDevice
import bb.lanxing.device.sgdevcie.xpair.uimodel.XPairUIModel
import bb.lanxing.device.sgdevcie.xpair.viewmodel.SearchDeviceViewModel
import bb.lanxing.device.sgdevcie.xpair.viewmodel.XPairViewModel
import bb.lanxing.mvvm.base.BaseDBFragment
import bb.lanxing.util.ui.IndicatorTipsBottomSheetDialog
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.withContext

class XPairSearchFragment :
    BaseDBFragment<FragmentXpairSearchBinding>(R.layout.fragment_xpair_search) {
    private val xPairViewModel by activityViewModels<XPairViewModel>()
    private val searchViewModel by activityViewModels<SearchDeviceViewModel>()

    private val adapter = SearchDeviceAdapter.defaultInstance().apply {
        setOnItemClickListener { adapter1, _, position -> goPair(adapter1.getItem(position) as BleDescriptionDevice) }
    }
    private val mutex: Mutex = Mutex()
    private var currentState: SearchState? = null
    private var jobTimeOut: Job? = null

    override fun initView(t: FragmentXpairSearchBinding) {
        setUpUiWithState(SearchState.searching)
        val imageView = binding.imgSearching
        val drawable = ResourcesCompat.getDrawable(
            resources, R.drawable.animate_drawable_xpair_searching, null
        )
        val animationDrawable = drawable as AnimationDrawable
        animationDrawable.start()
        imageView.background = animationDrawable
        val xPairUIModel: XPairUIModel? = xPairViewModel.xPairUIModel
        if (xPairUIModel != null) {
            binding.imgDevice.setImageResource(xPairUIModel.deviceIcon)
            val search = xPairUIModel.xPairSearchUIModel
            search?.let {
                val recyclerView = binding.recyclerViewFoundMore
                adapter.searchDeviceType = it.searchType
                recyclerView.adapter = adapter
                recyclerView.layoutManager = LinearLayoutManager(context)
                recyclerView.itemAnimator = DefaultItemAnimator()

                searchViewModel.deviceArrivalCallback = {
                    if (it.name.isNotEmpty()) {
                        lifecycleScope.launch {
                            mutex.lock()
                            try {
                                adapter.addDevice(it)
                                if (adapter.data.isNotEmpty()) {
                                    setUpUiWithState(SearchState.found);
                                } else {
                                    setUpUiWithState(SearchState.searching);
                                }
                            } catch (th: Throwable) {
                                mutex.unlock()
                                throw th
                            }
                            mutex.unlock()
                        }
                    }
                }
                val tips = it.searchTips
                tips?.let {
                    for ((index, item) in it.withIndex()) {
                        val inflate: LayoutXpairIntroItemBinding =
                            LayoutXpairIntroItemBinding.inflate(
                                layoutInflater
                            )
                        inflate.tvIndex.text = (index + 1).toString()
                        inflate.tvContent.text = item
                        binding.llSearchTips.addView(inflate.root)
                    }
                }
            }
        }
        binding.tvRetry.setOnClickListener {
            clear()
            startScan()
        }
        binding.tvTroubleshooting.setOnClickListener {
            val xPairUIModel = xPairViewModel.xPairUIModel
            val deviceName = xPairUIModel?.deviceName ?: ""
            val on = getString(
                R.string.st_ensure_device_bluetooth_is_turned_on, deviceName
            )
            val off = getString(
                R.string.st_turn_your_phone_bluetooth_off_on
            )

            val device = getString(
                R.string.st_restart_your_device, deviceName
            )

            val quit_device = getString(
                R.string.st_quit_and_restart_device, deviceName
            )

            val restart = getString(
                R.string.st_restart_your_phone
            )
            IndicatorTipsBottomSheetDialog.show(
                requireContext(), layoutInflater, IndicatorTipsBottomSheetDialog.IndicatorTipsBean(
                    listOf(
                        on, off, device, quit_device, restart
                    )
                )
            )
        }
        binding.tvPairNow.setOnClickListener {
            goPair(adapter.getItem(0))
        }
    }

    private fun setUpUiWithState(searchState: SearchState) {
        if (currentState == searchState) {
            if (currentState == SearchState.found) return
        }
        val i: Int = searchState.ordinal
        when (i) {
            0 -> {
                val binding6 = binding
                val linearLayoutCompat3 = binding6?.llSearching
                if (linearLayoutCompat3 != null) {
                    linearLayoutCompat3.visibility = View.VISIBLE
                    linearLayoutCompat3.clearAnimation()
                    val alphaAnimation = AlphaAnimation(linearLayoutCompat3.alpha, 1.0f)
                    alphaAnimation.duration = 500L
                    linearLayoutCompat3.startAnimation(alphaAnimation)
                }
                val binding8 = binding
                val linearLayoutCompat5 = binding8?.llFound
                if (linearLayoutCompat5 != null) {
                    linearLayoutCompat5.visibility = View.GONE
                }
                val binding9 = binding
                val frameLayout4 = binding9?.llFailed
                if (frameLayout4 != null) {
                    frameLayout4.visibility = View.GONE
                }
                this.currentState = SearchState.searching
                jobTimeOut?.cancel()
            }

            1 -> {
                val binding10 = binding
                val linearLayoutCompat6 = binding10?.llSearching
                if (linearLayoutCompat6 != null) {
                    linearLayoutCompat6.visibility = View.GONE
                }
                val binding11 = binding
                val linearLayoutCompat7 = binding11?.llFound
                if (linearLayoutCompat7 != null) {
                    linearLayoutCompat7.visibility = View.VISIBLE
                    linearLayoutCompat7.clearAnimation()
                    val alphaAnimation2 = AlphaAnimation(linearLayoutCompat7.alpha, 1.0f)
                    alphaAnimation2.duration = 500L
                    linearLayoutCompat7.startAnimation(alphaAnimation2)
                }
                val binding13 = binding
                val frameLayout5 = binding13?.llFailed
                if (frameLayout5 != null) {
                    frameLayout5.visibility = View.GONE
                }
                this.currentState = SearchState.found
            }

            2 -> {
                val binding14 = binding
                val linearLayoutCompat9 = binding14?.llSearching
                if (linearLayoutCompat9 != null) {
                    linearLayoutCompat9.visibility = View.GONE
                }
                val binding15 = binding
                val linearLayoutCompat10 = binding15?.llFound
                if (linearLayoutCompat10 != null) {
                    linearLayoutCompat10.visibility = View.GONE
                }
                val binding16 = binding
                val frameLayout6 = binding16?.llFailed
                if (frameLayout6 != null) {
                    frameLayout6.visibility = View.VISIBLE
                    frameLayout6.clearAnimation()
                    val alphaAnimation3 = AlphaAnimation(frameLayout6.alpha, 1.0f)
                    alphaAnimation3.duration = 500L
                    frameLayout6.startAnimation(alphaAnimation3)
                }
                val binding18 = binding
                val textView2 = binding18?.tvFailedDes
                if (textView2 != null) {
                    val xPairUIModel: XPairUIModel? = xPairViewModel.xPairUIModel
                    val string = if (xPairUIModel != null) xPairUIModel.deviceName else ""
                    textView2.text =
                        getString(R.string.we_are_having_some_trouble_locating_your_device, string)
                }
                this.currentState = SearchState.failed
            }
        }
    }

    private fun clear() {
        searchViewModel.stopScan()
        adapter.clear()
        jobTimeOut?.cancel()
    }

    private fun startScan() {
        searchViewModel.startScan()
        lifecycleScope.launch(Dispatchers.IO) {
            delay(60000L)
            withContext(Dispatchers.Main) {
                setUpUiWithState(SearchState.failed)
                searchViewModel.stopScan()
            }
        }
    }

    private fun goPair(bleDescriptionDevice: BleDescriptionDevice) {
        if (bleDescriptionDevice.itemType == 1) {
            goFirmWareUpdate(bleDescriptionDevice)
            val activity = activity
            if (activity != null) {
                activity.finish()
                return
            }
            return
        }
        this.findNavController().navigate(R.id.action_XPairSearchFragment_to_XPairPairingFragment)
        xPairViewModel.pairTarget = bleDescriptionDevice
    }

    private fun goFirmWareUpdate(bleDescriptionDevice: BleDescriptionDevice) {
//        val companion: UpdateDeviceIntroActivity.Companion = UpdateDeviceIntroActivity.Companion
//        val requireContext = requireContext()
//        companion.start(requireContext, bleDescriptionDevice.address, bleDescriptionDevice.name)
    }

    override fun onResume() {
        super.onResume()
        val xPairUIModel: XPairUIModel? = xPairViewModel.xPairUIModel
        sendMessage(
            R.id.msg_change_title,
            getString(R.string.st_pair_your_device, xPairUIModel?.deviceName ?: "")
        )
        startScan()
    }

    override fun onPause() {
        super.onPause()
        clear()
    }
}